package com.moli.iov.admin.websocket.service.query.impl;

import com.moli.iov.admin.utils.Contant;
import com.moli.iov.admin.websocket.model.MonitorRealTimeBarResVo;
import com.moli.iov.admin.websocket.model.MonitorRealTimeInfoResVo;
import com.moli.iov.admin.websocket.model.MonitorResVo;
import com.moli.iov.admin.websocket.service.AbstractWebSocketQueryService;
import com.moli.iov.admin.websocket.service.WebSocketQueryService;
import com.moli.iov.alarm.model.dto.req.AlarmInfoReqDto;
import com.moli.iov.alarm.remote.IAlarmRemoteService;
import com.moli.iov.base.model.po.VehicleBase;
import com.moli.iov.base.remote.IVehicleBaseRemoteService;
import com.moli.iov.protocol.enums.realtime.LocationStateTag;
import com.moli.iov.protocol.model.realtime.ExtendVehicleState;
import com.moli.iov.protocol.model.realtime.RealTimeInfo;
import com.moli.iov.protocol.model.realtime.RealTimeInfoReq;
import com.moli.iov.protocol.model.realtime.VehicleGpsReq;
import com.moli.iov.protocol.util.RealTimeInfoUtil;
import com.moli.iov.real.service.IRealService;
import com.moli.iov.rest.RestResponse;
import com.moli.iov.util.CoordTransformUtil;
import com.moli.iov.util.JsonUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.*;

/**
 * @ClassName VehicleMonitorWServiceImpl
 * @Description TODO
 * @Author 李伟松
 * @CreateDate 2019-03-07 上午 10:48
 * @UpdateDate 2019-03-07 上午 10:48
 * @Version 1.0
 */
@Slf4j
@Service("vehicleMonitorWService")
public class VehicleMonitorWServiceImpl extends AbstractWebSocketQueryService<List<String>> implements WebSocketQueryService {

    @Reference(group = "${service.group}", check = false)
    IVehicleBaseRemoteService vehicleBaseService;

    @Reference(group = "${service.group}", check = false)
    IRealService realService;

    @Reference(group = "${service.group}", check = false)
    IAlarmRemoteService iAlarmRemoteService;


    @Override
    public List<String> buildParam(String string) throws Exception {
        log.info("请求参数：{}",string);
        List<String> list = JsonUtils.parse(string,List.class);
        if(list!=null && list.size()>0){
            StringBuffer sb = new StringBuffer();
            for (String s : list) {
                sb.append(s);
                sb.append(", ");
            }
            log.info("序列化请求参数：{}",sb.toString());
        }

        return list;
    }


    private MonitorResVo setBar(List<String> vins) throws Exception {

        //vinList第一个元素为被选中车辆截取位置
        Integer sub = Integer.parseInt(vins.get(0));
        List<String> selectedVinList = vins.subList(1,sub+1);
        Set<String> selectedVinSet = new HashSet<>(selectedVinList);
        vins.remove(vins.get(0));

        //获取车辆在线数据
        Map<String, Boolean> onlineMap = getOnlineMap(vins);

        //获取车辆定位数据
        Map<String, Boolean> locationMap = getLocationMap(vins);

        //获取报警数
        Map<String, Integer> alarmMap = getAlarmMap(vins);

        Integer allCount = vins.size()-1;
        Integer selectedCount = selectedVinList.size();
        Integer allOnlineCount = 0;
        Integer selectedOnlineCount = 0;
        Integer allOfflineCount = 0;
        Integer selectedOfflineCount = 0;
        Integer allAlarmCount = 0;
        Integer selectedAlarmCount = 0 ;
        Integer allOnlineLocalCount = 0;
        Integer selectedOnlineLocalCount = 0 ;

        for (String vin : vins) {
            if(onlineMap.get(vin)==null || !onlineMap.get(vin)){
                allOnlineCount++;
                if(selectedVinSet.contains(vin)){
                    selectedOnlineCount++;
                }

                if(locationMap.get(vin)!=null && locationMap.get(vin)){
                    allOnlineLocalCount++;
                    if(selectedVinSet.contains(vin)){
                        selectedOnlineLocalCount++;
                    }
                }

            }else{
                allOfflineCount++;
                if(selectedVinSet.contains(vin)){
                    selectedOfflineCount++;
                }
            }

            if(alarmMap.get(vin)!=null && alarmMap.get(vin)==1){
                allAlarmCount++;
                if(selectedVinSet.contains(vin)){
                    selectedAlarmCount++;
                }
            }
        }

        MonitorResVo res = new MonitorResVo();
        MonitorRealTimeBarResVo monitorBar = new MonitorRealTimeBarResVo();
        monitorBar.setAlarmCount(selectedAlarmCount+"/"+allAlarmCount);
        monitorBar.setAllCount(selectedCount+"/"+allCount);
        monitorBar.setOfflineCount(selectedOfflineCount+"/"+allOfflineCount);
        monitorBar.setLocationCount(selectedOnlineLocalCount+"/"+allOnlineLocalCount);
        monitorBar.setOnlineCount(selectedOnlineCount+"/"+allOnlineCount);
        res.setMonitorBar(monitorBar);
        return res;
    }

    @Override
    public RestResponse get(List<String> vinList,String token) {

        if (vinList == null || vinList.isEmpty()) {
            return RestResponse.failure("无效参数");
        }

        try {
            if (vinList == null || vinList.size() < 2
                    || StringUtils.isEmpty(vinList.get(0))
                    ||(Integer.parseInt(vinList.get(0)))>(vinList.size()+1)) {
                return RestResponse.failure("查询参数vinList 不能为空");
            }

//            Set<String> vinSet = new HashSet<String>(vinList);
            List<String> vins = new ArrayList<>(vinList);
            vins.removeAll(Collections.singleton(null));
            if (vins.size() < 1) {
                return RestResponse.failure("参数vinList异常 ");
            }

            //vinList第一个元素为被选中车辆截取位置
            String index = vins.get(0);
            Integer sub = Integer.parseInt(index);
            List<String> selectedVinList = vins.subList(1,sub+1);
            Set<String> selectedVinSet = new HashSet<>(selectedVinList);

            //获取车辆在线数据
            Map<String, Boolean> onlineMap = getOnlineMap(vins);

            //获取车辆定位数据
            Map<String, Boolean> locationMap = getLocationMap(vins);

            //获取报警数
            Map<String, Integer> alarmMap = getAlarmMap(vins);

            Integer allCount = vins.size()-1;
            Integer selectedCount = selectedVinList.size();
            Integer allOnlineCount = 0;
            Integer selectedOnlineCount = 0;
            Integer allOfflineCount = 0;
            Integer selectedOfflineCount = 0;
            Integer allAlarmCount = 0;
            Integer selectedAlarmCount = 0 ;
            Integer allOnlineLocalCount = 0;
            Integer selectedOnlineLocalCount = 0 ;

            for (String vin : vins) {
                if(!vin.equals(index)){
                if(onlineMap.get(vin)==null || !onlineMap.get(vin)){
                    allOfflineCount++;
                    if(selectedVinSet.contains(vin)){
                        selectedOfflineCount++;
                    }
                }else{
                    allOnlineCount++;
                    if(selectedVinSet.contains(vin)){
                        selectedOnlineCount++;
                    }

                    if(locationMap.get(vin)!=null && locationMap.get(vin)){
                        allOnlineLocalCount++;
                        if(selectedVinSet.contains(vin)){
                            selectedOnlineLocalCount++;
                        }
                    }
                }

                if(alarmMap.get(vin)!=null && alarmMap.get(vin)==1){
                    allAlarmCount++;
                    if(selectedVinSet.contains(vin)){
                        selectedAlarmCount++;
                    }
                }
                }
            }

            MonitorResVo res = new MonitorResVo();
            MonitorRealTimeBarResVo monitorBar = new MonitorRealTimeBarResVo();
            monitorBar.setAlarmCount(selectedAlarmCount+"/"+allAlarmCount);
            monitorBar.setAllCount(selectedCount+"/"+allCount);
            monitorBar.setOfflineCount(selectedOfflineCount+"/"+allOfflineCount);
            monitorBar.setLocationCount(selectedOnlineLocalCount+"/"+allOnlineLocalCount);
            monitorBar.setOnlineCount(selectedOnlineCount+"/"+allOnlineCount);
            res.setMonitorBar(monitorBar);


            List<MonitorRealTimeInfoResVo> monitorInfoList = new ArrayList<>();

            //获取车辆实时数据
            if(selectedVinList!=null){
                RestResponse<List<RealTimeInfo>> infoRes = realService.listRealTimeInfo(selectedVinList);
                Map<String, String> vinLinceseMap = getVinLincenseMap(selectedVinList);

                if (infoRes != null) {
                    List<RealTimeInfo> realTimeInfoList = infoRes.getData();
                    if (infoRes.getData() != null && infoRes.getData().size() > 0) {
                        for (RealTimeInfo dto : realTimeInfoList) {
                            MonitorRealTimeInfoResVo infoResVo = this.getMonitorRealTimeInfoResVo(dto, onlineMap, vinLinceseMap);
                            if (infoResVo != null) {
                                monitorInfoList.add(infoResVo);
                            }
                        }
                    }
                }
            }

            res.setMonitorInfoList(monitorInfoList);

            return RestResponse.success(res);
        } catch (Exception e) {
            log.error("[查询服务异常][{}][{}]", vinList, e.getMessage(), e);
            return RestResponse.failure("查询服务异常");
        }

    }

    private Map<String,Integer> getAlarmMap(List<String> vins){
        AlarmInfoReqDto alarmInfoReqDto = new AlarmInfoReqDto();
        alarmInfoReqDto.setVins(vins);
        RestResponse<Map<String, Integer>> alarmRes = iAlarmRemoteService.getTotalAlarmingByVins(alarmInfoReqDto);
        Map<String, Integer> alarmMap = new HashMap<>();
        if(alarmRes!=null && alarmRes.getData()!=null){
            alarmMap = alarmRes.getData();
        }
        return alarmMap;
    }

    private Map<String,Boolean> getLocationMap(List<String> vins){
        //获取车辆定位数据
        RestResponse<Map<String, Boolean>> locationRes = null;
        try {
            locationRes = realService.isLocationVinMap(vins);
        } catch (Exception e) {
            e.printStackTrace();
        }
        Map<String, Boolean> locationMap = new HashMap<>();
        if(locationRes!=null && locationRes.getData()!=null){
            locationMap = locationRes.getData();
        }
        return locationMap;
    }

    private Map<String ,Boolean> getOnlineMap(List<String> vins){
        //获取车辆在线数据
        RestResponse<Map<String, Boolean>> onlineRes = null;
        try {
            onlineRes = realService.isOnlineMap(vins);
        } catch (Exception e) {
            e.printStackTrace();
        }
        Map<String, Boolean> onlineMap = new HashMap<>();
        if (onlineRes != null) {
            onlineMap = onlineRes.getData();
        }
        return onlineMap;
    }

    private Map<String,String > getVinLincenseMap(List<String>  vins){
        //        获取车辆基础数据
        Map<String, String> vinLinceseMap = new HashMap<>();
//        VehicleBaseQueryListReqDto vehicleBaseQueryListDto =new VehicleBaseQueryListReqDto();
        RestResponse<Map<String, VehicleBase>> vehicleBaseMap = vehicleBaseService.listVehicleBaseByVin(vins);
        if (vehicleBaseMap != null && vehicleBaseMap.getData() != null) {
            Collection<VehicleBase> vehicleBaseList = vehicleBaseMap.getData().values();
            if (vehicleBaseList != null && vehicleBaseList.size() > 0) {
                vehicleBaseList.stream().forEach(vehicleBase -> {
                    if (!StringUtils.isEmpty(vehicleBase.getVin())) {
                        vinLinceseMap.put(vehicleBase.getVin(), vehicleBase.getLicense());
                    }
                });
            }
        }
        return vinLinceseMap;
    }

    private MonitorRealTimeInfoResVo getMonitorRealTimeInfoResVo(RealTimeInfo info, Map<String, Boolean> onlineMap, Map<String, String> vinLinceseMap) {

        if (info != null && info.getRealTimeInfoReq()!=null && !StringUtils.isEmpty(info.getVin())) {
            RealTimeInfoReq dto = info.getRealTimeInfoReq();
            MonitorRealTimeInfoResVo vo = new MonitorRealTimeInfoResVo();

            String license = vinLinceseMap.get(info.getVin());
            if (StringUtils.isEmpty(license)) {
                license = Contant.NULL;
            }
            vo.setLicense(license);
            vo.setVin(info.getVin());
            if (onlineMap != null) {
                vo.setOnlineStatus(onlineMap.get(info.getVin()));
            }

            vo.setExtendGpsDirection(RealTimeInfoUtil.getGpsDirection(dto.getExtendReq().getextendVehicleState()));
            vo.setSpeed(RealTimeInfoUtil.getSpeed(dto.getVehicleAllReq()));

            VehicleGpsReq vehicleGps = dto.getVehicleGpsReq();
            if (vehicleGps != null) {

                double[] local = CoordTransformUtil.transformWGS84ToBD09(RealTimeInfoUtil.getLongitude(vehicleGps), RealTimeInfoUtil.getLatitude(vehicleGps));
                vo.setLatitude(local[1]);
                vo.setLongitude(local[0]);
                LocationStateTag locationState = vehicleGps.getLocationState();
                vo.setLocaltionStatus(RealTimeInfoUtil.getLocationStatus(locationState));
            }

            if(dto.getExtendReq()!=null ){
                ExtendVehicleState state = dto.getExtendReq().extendVehicleState;
                vo.setPowerGear(RealTimeInfoUtil.getPowerGear(state));
            }

            vo.setAlarmStatus(false);

            //车辆状态赋值 1、在线定位，2、在线未定位，3、报警，4、不在线
            if (vo.getOnlineStatus()!=null && vo.getOnlineStatus()) {
                if (vo.getLocaltionStatus()!=null && vo.getLocaltionStatus()) {
                    vo.setVehicleStatus(1);
                } else {
                    vo.setVehicleStatus(2);
                }
            } else {
                vo.setVehicleStatus(4);
            }
            if (vo.getAlarmStatus()!=null && vo.getAlarmStatus()) {
                vo.setVehicleStatus(3);
            }
            return vo;
        }
        return null;
    }
}
